#ifndef PLATTHREADLINUX
#define PLATTHREADLINUX
#include <pthread.h>

namespace Platinum{
	namespace Thread{
		typedef void (*TFunc)(void*);
		
		typedef pthread_t ThreadID;
		
		class DummyData {
			public:
				TFunc m_func;
				void* m_data;
		};

		void* DummyRun( void* p_data )
		{
			// convert the dummy data
			DummyData* data = (DummyData*)p_data;
			
			// run the function with the given data
			data->m_func( data->m_data );
			
			// now delete the data
			delete data;
			
			// and return 0.
			return 0;
		}
		
		inline ThreadID Create(TFunc p_func, void* p_param ){
			ThreadID t;
			// create a new dummy data block
			DummyData* data = new DummyData;
			data->m_func = p_func;
			data->m_data = p_param;
			
			pthread_create( &t, 0, DummyRun, data );
			
			if( t == 0 ) {
				// delete the data first
				delete data;
				// throw an error
				throw Error(666, "Thread Creation Failure!" );
			}
				return t;
		}
		
		inline ThreadID GetID() {
			return pthread_self();
		}
		
		inline void WaitForFinish( ThreadID p_thread ) {
			// "join" the thread. This essentially transfers control over to
			// the thread and waits for it to finish.
			pthread_join( p_thread, NULL );
		}
		
		inline void Kill( ThreadID& p_thread ) {
			// cancel the thread.
			pthread_cancel( p_thread );
		}
		
		inline void Yield( int p_milliseconds = 1 ) {
			usleep( p_milliseconds * 1000 );
		}
	
		class Mutex {
			protected:
				// define the base mutex types
				pthread_mutex_t m_mutex;
			public:
				Mutex(){
					pthread_mutex_init( &m_mutex, 0 );
				}
			
				~Mutex() {
					pthread_mutex_destroy( &m_mutex );
				}
		
				inline void Lock() {
					pthread_mutex_lock( &m_mutex );
				}
				
				inline void Unlock() {
					pthread_mutex_unlock( &m_mutex );
				}
		};  // end class Mutex

	}
}
#endif

